
SIMPLER GLCD CODING

Dear EPE,

Thank you for running your PIC Tutorial V2, it has lots more useful
information and is well worth reading over and over. Under the I2C section
I notice you haven't used this format on PICs other than the 16F87x. In the
16F84 to glcd routine I sent you and which you put on your ftp site, there
is an I2C routine that should run on most PICs, but may need tidying.

Also, a long while back, I read John Becker's Using Graphics L.C.D.s and
experimented with another glcd device. I also sent John an ASM listing for
running a graphics l.c.d. (glcd) via shift registers and said I would apply
my findings to a normal glcd hook-up. I have found that status checks are
not necessary on glcds and simple timing delays work even at a 20MHz PIC
clock. This means a large-ish saving in code space and eases the learning
curve a bit.

Part of getting to grips with glcds was learning more about "normal" text
l.c.d.s. Using a shift register interface, I ended up with a routine that
will setup an alphanumeric l.c.d., with timing, s/r, command, character and
number sub-routines, in 35 PIC commands. This too will run at 20MHz. As it
only uses any three I/O pins (two of which could be used as inputs when no
l.c.d. work is in progress) you might find it useful in prog development
when I/O pins are in short supply.

I include here my "timing" routine for glcds based around John's SENDCMD
subroutine. I had a little trouble understanding the original SENDCMD and
particularly OUTDATA subs, but then I realised that any change to D0-D7,
CD, RD and WR had no effect until CE is clocked low. This simplistic view
was applied to the following subs in which CE is the key. Finding the
timing was simply a matter of counting passes through BTFSC in the CHECK
subs in his GEPE456 prog.

The T6963 chip (as in John's glcd example) is a lot faster than the HD4470
used in some other l.c.d.s and approximately 8us delay is used with a built
in safety margin and only applied to command data. PICs don't appear to run
fast enough to "overload" on auto write data input. Interestingly, the
first call to PAUSIT isn't needed! I didn't even change INTCON settings.

I appreciate John's efforts in getting glcds to work, especially with the
limited data available, and understand any reluctance to change tack. It
gave me something to tune ( I don't make engines, I rebuild, modify and
tune them ). Here's my code for the 20MHz glcd version, which will also
work with any slower crystal rate. Change CLKCNT BSF values if time is at a
premium Replace the existing SENDCMD and OUTDATA subroutines with the
following   Also rem out all calls for CHECKS 3, 6, 8, and . replace all
calls to AUTOWRITE with CALL OUTDATA.

SENDCMD: movwf PORTD     ; place word on D0-D7
         bsf CLKCNT,5    ; value is nearest Xtal whole number * 1.5
SC:      decfsz CLKCNT,f ; rough timer to give over 8us
         goto SC
         movlw %00011010
         movwf PORTC     ; set CE, WR low
         goto DWELL      ; wait for port to stabilise

OUTDATA: movwf PORTD     ; place word on D0-D7
         movlw %00010010 ;  1   0   0   1   0
         movwf PORTC     ; set CD, CE, WR low
DWELL:   bsf CLKCNT,3    ; use bsf temp,3 above 15MHz, 2 above 10MHz,
                         ; 1 above 5MHZ & 0 under 5MHz
TIME:    decfsz CLKCNT,f ; rough timer to give about 2us
         goto TIME
         bsf PORTC,2     ; data & control line words "clocked in"
         return

Graham Card, via email

Interesting that you've got round the check situation - well done Graham. I
have put your above code into PIC Tricks on our ftp site, together with the
longer example program you sent, and its additional notes.

Of course, using a timing delay will be familiar to anyone using
alphanumeric displays as the this is the only technique is use with these
devices in EPE projects. Regarding PAUSIT, have you checked that the glcd
will initialise immediately power is switched on, even with a power supply
that have as slow rise-time for its final regulated voltage?

I haven't yet had the need for I2C on an F84 but I'll keep your previous
code in mind should I do so, thanks for it. Continue enjoying your PICing!

***********************

ADDITIONAL INFORMATION FROM GRAHAM NOT PUBLISHED IN READOUT

John, as you are posting my glcd timing code on the FTP site perhaps you
might include the following notes on how I arrived at the end result. Also
I used CLKCNT as I didn't need it for anything else. It might mess up a
clock routine if anyone should try it. Have added TEMP instead. I have
included a compressed setup routine, initialisation routines are done on
run-through, all others called as required. The notes are guesswork only.
All I really know is that it works.

Toshiba's data sheet gives a 200ns timing for data, but warns of hardware
lockout if MSB = 0. (MSBit or MSByte?). A finite time should be taken for
such lockout & worst case was approx 5us. Have allowed approx 8us but on
commands only. 8 bit data entry (autowrite) is dependant on risetime on CE
pin. PIC risetime seems a little slow, needing 2us to clock CE high (or to
allow glcd time to swallow data). Given 200ns timing I can't see a PIC
overrunning data entry on autowrite.

Toshiba data sheet also gives a 2us "bootup" timing, so by the time the PIC
has woken up & run through basic settings, glcd is ready for action.
Initial "pausit" routine is not needed. Complete setup & user routines.
Call SETUP to use, will return as normal 20MHz version, will work with any
slower xtal. Change TEMP bsf values if time is at a premium.

Replace these subs & rem out all calls for CHECKS 3,6 & 8. Replace all
calls for AUTOWRITE with "call OUTDATA". Remove AWRON & AWROFF Equates.
Replace all "movlw AWRON call SENDCMD" & "movlw AWROFF call SENDCMD" with
"call AWRON & call AWROFF" respectively.

BITWRITE:  movwf BITVAL
           call SCREENADR    ; set screen write address
           movf BITVAL,W
           call SENDCMD      ; send command
           return            ;
ONEWRITE:  movwf ATTRIB      ; temp store val brought in on W
           call SCREENADR    ; set screen write address - vals preset
                             ; at call
           call AWRON        ; AUTO WRITE ON
           movf ATTRIB,W
           call OUTDATA
           call AWROFF       ; AUTO WRITE OFF
           return
CMDADR:    movf ADRLSB,W     ; WRITE DATA D1
           call OUTDATA      ;
           movf ADRMSB,W     ; WRITE DATA D2
           call OUTDATA      ;
           retlw $22         ; offset command (setup only)
SCREENADR: call CMDADR       ;
           movlw ADPSET      ; SET ADDRESS POINTER
           call SENDCMD      ; send command
           return            ;
TEXTHOME:  clrf ADRMSB       ; TEXT HOME ADDRESS $0000
           clrf ADRLSB       ;
           call CMDADR       ; send command address
           movlw TXHOME      ;
           call SENDCMD      ; send command
           return
GRAPHHOME: movlw $02         ; GRAPHIC HOME ADDRESS $0200
           movwf ADRMSB
           clrf ADRLSB
           call CMDADR       ; send command address
           movlw GRHOME      ;
           call SENDCMD      ; send command
           return
TEXTAREA:  clrf ADRMSB       ;
           movf COLUMN,W     ; columns length
           movwf ADRLSB      ;
           call CMDADR       ; send command address
           movlw TXAREA      ; text area command
           call SENDCMD      ; send command
           return
GRAPHAREA: clrf ADRMSB       ;
           movf COLUMN,W     ; columns length
           movwf ADRLSB      ;
           call CMDADR       ; send command address
           movlw GRAREA      ; graphic area command
           call SENDCMD      ; send command
           retlw %10000000   ; set mode value (SETUP routine only)
CSRADR:    call CMDADR       ; send command address
           movlw CSRPOS      ; cursor position command
           call SENDCMD      ; send command
           return
SETUP:     call TEXTHOME     ; SET TEXT HOME ADDRESS
           call GRAPHHOME    ; SET GRAPHIC HOME ADDRESS
           call TEXTAREA     ; SET TEXT AREA
           call GRAPHAREA    ; SET GRAPHIC AREA
           call SENDCMD      ; SET MODE (INT/EXT/AND-OR-XOR etc)
                             ; see grapharea retlw
           movlw 2           ; SET OFFSET (see EPE text) ADRMSB cleared
                             ; earlier (SETUP routine only)
           movwf ADRLSB      ;
           call CMDADR       ; send command address (return with OFFSET
                             ; ($22) in W) (SETUP routine only)
           call SENDCMD      ; send command
           movlw %10011111   ; display mode setting (SETUP routine only)
           call SENDCMD      ; DISPLAY MODE (text, graph on/off etc)
           call CLRTXT       ; WRITE TEXT BLANK CODE $0000
           call CLRGRAPH     ; WRITE GRAPH BLANK CODE $0200, then default
                             ; to CLRCG
CLRCG:     movlw $14         ; * CLEAR CG AREA * last op of setup
           goto CG
CLRGRAPH:  movlw $02         ; ** CLEAR GRAPH AREA ($0200) **
CG:        movwf ADRMSB      ;
           clrf ADRLSB       ;
           call SCREENADR    ; set screen write address
           call AWRON        ; AUTO WRITE ON
           movlw 64          ; number of lines
           movwf LOOPC
           goto CLR
CLRTXT:    clrf ADRMSB       ; clear all text screen lines, length as set
           clrf ADRLSB       ;
           call SCREENADR    ; set screen write address
           call AWRON        ; AUTO WRITE ON
           movlw 8           ; number of lines
           movwf LOOPC
CLR:       movf COLUMN,W     ; column length
           movwf LOOPB       ;
CLR1:      movlw 0           ; write 0
           call OUTDATA      ;
           decfsz LOOPB,F    ;
           goto CLR1         ;
           decfsz LOOPC,F    ;
           goto CLR          ;
           call AWROFF       ; AUTO WRITE OFF
           return
SETCG:     movlw $14         ; CG RAM start address 1400H
           movwf ADRMSB      ;
           clrf ADRLSB       ;
           call SCREENADR    ; set screen write address
           return
SETATTR:   call SCREENADR    ; set screen write address - vals preset
                             ; at call
           call AWRON        ; AUTO WRITE ON
SETAT:     movf ATTRIB,W     ; val to be sent preset at call
           call OUTDATA      ;
           decfsz LOOPC,F    ; LOOPC val specified by calling routine
           goto SETAT        ;
           call AWROFF       ; AUTO WRITE OFF
           return

AWRON:     movlw 176               ; AUTO WRITE ON
           goto SENDCMD      ; send command
AWROFF:    movlw 178         ; AUTO RESET put here to default to SENDCMD
SENDCMD:   movwf PORTD       ; place word on D0-D7
           bsf TEMP,2        ; value is nearest Xtal whole number * 1.5
SC:        decfsz TEMP,f     ; rough timer to give over 8 u/s
           goto SC
           movlw %00011010
           movwf PORTC       ; set CE, WR low
           goto DWELL        ; wait for port to stabilise
OUTDATA:   movwf PORTD       ; place word on D0-D7
           movlw %00010010   ;  1   0   0   1   0
           movwf PORTC       ; set CD, CE, WR low

DWELL:     bsf TEMP,0        ; use bsf temp,3 above 15 MHz ,2
                             ; above 10MHz ,1 above 5MHZ & ,0 under 5 MHz
TIME:      decfsz TEMP,f     ; rough timer to give about 2 u/s
           goto TIME
           bsf PORTC,2       ; data & control line words "clocked in"
           return

